package utility

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha1"
	"crypto/x509"
	"encoding/pem"
	"errors"
	"fmt"
	"github.com/gogf/gf/v2/crypto/gaes"
	"github.com/gogf/gf/v2/crypto/gmd5"
	"github.com/gogf/gf/v2/crypto/gsha1"
	"github.com/gogf/gf/v2/encoding/gbase64"
	"github.com/gogf/gf/v2/encoding/gurl"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/ghttp"
	"github.com/gogf/gf/v2/os/gfile"
	"github.com/gogf/gf/v2/text/gstr"
	"github.com/gogf/gf/v2/util/gconv"
	"github.com/mojocn/base64Captcha"
	"miaoyu/internal/consts"
	"net/url"
	"strings"
)

// 判断用户登录状态

func GetOssUrl() string {
	v := ""
	if v == "null" {
		return ""
	}
	return v
}

// InArray 判断元素是否在数组中
func InArray(value string, array []interface{}) bool {
	for _, v := range array {

		if gconv.String(v) == value {
			return true
		}
	}
	return false
}

func IsWechatClient(r *ghttp.Request) bool {
	userAgent := r.Header.Get("User-Agent")
	return strings.Contains(userAgent, "MicroMessenger")
}

/*
生成验证码
*/
type configJsonBody struct {
	Id            string
	CaptchaType   string
	VerifyValue   string
	DriverAudio   *base64Captcha.DriverAudio
	DriverString  *base64Captcha.DriverString
	DriverChinese *base64Captcha.DriverChinese
	DriverMath    *base64Captcha.DriverMath
	DriverDigit   *base64Captcha.DriverDigit
}

var store = base64Captcha.DefaultMemStore

func CaptchaGenerate() (idKey string, b64s string, err error) {
	// 验证码参数配置：字符,公式,验证码配置
	var driver base64Captcha.Driver
	var param = configJsonBody{
		Id:          "",
		CaptchaType: "string",
		VerifyValue: "",
		DriverAudio: &base64Captcha.DriverAudio{},
		DriverString: &base64Captcha.DriverString{
			Length:          4,
			Height:          60,
			Width:           240,
			ShowLineOptions: 8,
			NoiseCount:      0,
			Source:          "123456789qwertyuioplkjhgfdsazxcvbnm",
		},
		DriverChinese: &base64Captcha.DriverChinese{},
		DriverMath:    &base64Captcha.DriverMath{},
		DriverDigit:   &base64Captcha.DriverDigit{},
	}

	//choose driver
	switch param.CaptchaType {
	case "audio":
		driver = param.DriverAudio
	case "string":
		driver = param.DriverString.ConvertFonts()
	case "math":
		driver = param.DriverMath.ConvertFonts()
	case "chinese":
		driver = param.DriverChinese.ConvertFonts()
	default:
		driver = param.DriverDigit
	}
	c := base64Captcha.NewCaptcha(driver, store)
	idKey, b64s, _, err = c.Generate()

	return
}

func CaptchaVerify(idKey, verifyValue string) bool {
	var store = base64Captcha.DefaultMemStore
	match := store.Verify(idKey, verifyValue, true)
	return match
}

func MergeMaps(m1, m2 g.MapStrAny) g.MapStrAny {
	for k, v := range m2 {
		m1[k] = v
	}
	return m1
}

// ToInt64Array 带分隔符的字符串分裂成int64数组
func ToInt64Array(str, split string) []int64 {
	result := make([]int64, 0)
	if str == "" {
		return result
	}
	arr := strings.Split(str, split)
	if len(arr) > 0 {
		for i := range arr {
			if arr[i] != "" {
				result = append(result, gconv.Int64(arr[i]))
			}
		}
	}
	return result

}

// MD5String MD5哈希值
func MD5String(s string) (str string, err error) {
	str, err = gmd5.EncryptBytes([]byte(s))
	return
}

// SHA1String SHA1哈希值
func SHA1String(s string) (str string) {
	str = gsha1.Encrypt([]byte(s))
	return
}

// MakeAdminPassWord SHA1哈希值
func MakeAdminPassWord(s string) (str string) {
	s = s + "<miaoyuadmincode>"
	fmt.Println("加密后字符串", s)
	str = gsha1.Encrypt([]byte(s))
	return
}

// MakeWebPassWord SHA1哈希值
func MakeWebPassWord(s string) (str string) {
	s = s + "<miaoyuwebcode>"
	fmt.Println("加密后字符串", s)
	str = gsha1.Encrypt([]byte(s))
	return
}

// 私钥
var privateKey = []byte(`
-----BEGIN RSA PRIVATE KEY-----
MIIBOwIBAAJBAKsOod1ww3FQXDaNX3BowcxrKHKQIqLHFqwYbMwAcluISaPvSnQx
5TW9rDa5h6Zx3K96VKAEPSdBPKCOYt99y2ECAwEAAQJAZwJ2w01mxNQp08gq0xyi
qCFXyDW4ReIyawyCaA9Uzn01ZqKlC0Ewzi4Hs2w+uHqULtgGkGFc5HItCA6c7FA4
4QIhAOHVWbt1On961s2yX7fPjZsADdGnX0o6dVxmjYNAM0CFAiEAwegkH4FH1K5P
+pGO0cSKAsGLyzdiFv3gCiQ19BaB5C0CIF/C5m/0/786yYcj0i7RVgyZ80IppOCG
9WkfG3bCbHk5AiEAuFRRYpGnEwrRhMSyG77V42DR31C6sliMjZd2op5yw9ECIQCF
KbDFGtyqTZ6hWrgJ9KBo0bqTyZRtiUQU/OomGUh4uQ==
-----END RSA PRIVATE KEY-----
`)

// 公钥
var publicKey = []byte(`
-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKsOod1ww3FQXDaNX3BowcxrKHKQIqLH
FqwYbMwAcluISaPvSnQx5TW9rDa5h6Zx3K96VKAEPSdBPKCOYt99y2ECAwEAAQ==
-----END PUBLIC KEY-----
`)

// RsaEncrypt 加密
func RsaEncrypt(origData []byte) ([]byte, error) {
	block, _ := pem.Decode(publicKey) //将密钥解析成公钥实例
	if block == nil {
		return nil, errors.New("public key error")
	}
	pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes) //解析pem.Decode（）返回的Block指针实例
	if err != nil {
		return nil, err
	}
	pub := pubInterface.(*rsa.PublicKey)
	var rsaStr []byte
	rsaStr, err = rsa.EncryptPKCS1v15(rand.Reader, pub, origData)
	rsaStr64 := gbase64.Encode(rsaStr)
	return rsaStr64, err //RSA算法加密
}

// RsaDecrypt 解密
func RsaDecrypt(ciphertext64 []byte) ([]byte, error) {
	block, _ := pem.Decode(privateKey) //将密钥解析成私钥实例
	if block == nil {
		return nil, errors.New("private key error!")
	}
	priv, err := x509.ParsePKCS1PrivateKey(block.Bytes) //解析pem.Decode（）返回的Block指针实例
	if err != nil {
		return nil, err
	}
	ciphertext, err := gbase64.Decode(ciphertext64)

	var originData []byte
	originData, err = rsa.DecryptPKCS1v15(rand.Reader, priv, ciphertext) //RSA算法解密

	return originData, err
}

var aesKey = []byte("miaoyubylicxpro!")

func AesEncrypt(plainText string) (str string, err error) {
	byt, genErr := gaes.EncryptCBC(gconv.Bytes(plainText), aesKey)
	if genErr != nil {
		err = genErr
		return
	}
	str = gconv.String(gbase64.Encode(byt))
	return
}
func AesDecrypt(cipherText string) (str string, err error) {
	cipByte, _ := gbase64.Decode(gconv.Bytes(cipherText))
	byteStr, _ := gaes.DecryptCBC(cipByte, aesKey)
	str = gconv.String(byteStr)
	return
}

func Translator(m *g.MapIntStr, k int) string {
	for i, v := range *m {
		if i == k {
			return v
		}
	}
	return "空"
}
func GetRouteByKey(key string) string {

	keySlice := gstr.SplitAndTrim(key, "/")
	key = gstr.ToLower(gstr.Join(keySlice, "/")) + "!"
	//末尾加！ 考虑有些key值会包括，但不是匹配到结尾
	routeMapList := consts.RouteMap
	for _, val := range routeMapList {
		pStr := val.KeyName + "!"
		if gstr.Contains(pStr, key) {
			return val.Pattern
		}
	}
	return ""
}
func CheckRouteAuth(router string) bool {

	routeMapList := consts.RouteMap
	for _, val := range routeMapList {
		if val.IsLogin == false {
			if gstr.Contains(val.Pattern, router) {
				return true
			}
		}
	}
	return false
}

// UrlBuild 路径生成函数
/**

路径 path  规则xx.xx.xxX.do
参数 param
前缀 prefix  xx.xx.xxX
*/
//根据url拼凑类型
func UrlBuild(path string, param g.MapStrAny) string {
	var (
		urlParam = ""
		urlStr   = ""
	)

	if param != nil {
		urlValue := url.Values{}
		_ = gconv.Scan(param, &urlValue)
		urlParam = gurl.BuildQuery(urlValue)

	}
	if urlParam != "" {
		urlStr = path + "?" + urlParam
	} else {
		urlStr = path
	}

	return urlStr
}

const Test = "test"

// Signature 微信ticket签名
func Signature(jsTicket, nonceStr, timestamp, url string) string {
	h := sha1.New()
	h.Write([]byte(fmt.Sprintf("jsapi_ticket=%s&noncestr=%s&timestamp=%s&url=%s", jsTicket, nonceStr, timestamp, url)))
	return fmt.Sprintf("%x", h.Sum(nil))
}

func WriteFileContent(path, content string) error {
	// Check whether the file exists
	fErr := gfile.PutContents(path, content)
	//Creates file with given `path` recursively
	if fErr != nil {
		return fErr
	}
	return nil
}
